package top.ywlog.permission.filter;


import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * @author: Durian
 * @date: 2020/10/18 3:04
 * @description: 因为request的getReader和getInputStream只能调用一次
 * 在这个类中将 Request Body 保存，然后通过 Servlet 自带的 HttpServletRequestWrapper 类
 * 覆盖 getReader() 和getInputStream() 方法，使流从保存的body读取。
 * 然后再Filter中将ServletRequest替换为AuthenticationRequestWrapper。
 * <p>
 * 该类不能注册到Spring容器中，否则会报错
 */
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper
{
    private final String body;

    public RequestWrapper(HttpServletRequest request)
    {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        try (InputStream inputStream = request.getInputStream();
             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)))
        {
            char[] charBuffer = new char[128];
            int bytesRead;
            while ((bytesRead = bufferedReader.read(charBuffer)) > 0)
            {
                stringBuilder.append(charBuffer, 0, bytesRead);
            }
        } catch (IOException ex)
        {
            log.error("get request inputStream error :{}", ex.getMessage());
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream()
        {
            @Override
            public boolean isFinished()
            {
                return false;
            }

            @Override
            public boolean isReady()
            {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener)
            {
            }

            @Override
            public int read() throws IOException
            {
                return byteArrayInputStream.read();
            }
        };

    }

    @Override
    public BufferedReader getReader() throws IOException
    {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBody()
    {
        return this.body;
    }


}
